home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / patch12.arc / UTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-02  |  11.4 KB  |  520 lines

  1. /* $Header: pch.c,v 2.0.1 90/05/30 11:30:00 mward $
  2.  *
  3.  * $Log:    pch.c,v $
  4.  * Revision 2.0.1  90/05/30  11:30:00  mward
  5.  * modify calls to read, write to detect error on return of value -1
  6.  * added TURBOC20 ifdef stuff:
  7.  *    no inodes: modify move_file same file detect accordingly
  8.  *    no links:  modify move_file link calls to copy_file calls
  9.  *    no SIGHUP: modify signal routines accordingly
  10.  *
  11.  */
  12.  
  13. #include "EXTERN.h"
  14. #include "common.h"
  15. #include "INTERN.h"
  16. #include "util.h"
  17.  
  18. #ifdef TURBOC20
  19. #include <dir.h>
  20. /* fnappend : Append first char of bext to a MSDOS file name.
  21.  *            bext should not start with a letter or digit.
  22.  */
  23.  
  24. void
  25. fnappend(fspec,bext)
  26. char *fspec, *bext;
  27. {
  28.     char *fnmex;
  29.     char fname[MAXFILE];
  30.     char fext[MAXEXT];
  31.     int i,j;
  32.     int fnlen;
  33.     int felen;
  34.  
  35.     /* fnmex should point to first char of file name/extension
  36.      * (not path or drive)
  37.      */
  38.     fnmex = fspec + strlen(fspec);
  39.     while ((fnmex!=fspec) && (strchr("/\\:",*(fnmex-1))==NULL)) {
  40.         fnmex--;
  41.     }
  42.  
  43.     /* get file name and length */
  44.     for (fnlen=i=0; fnmex[i] && fnmex[i]!= '.' && i<MAXFILE-1; i++) {
  45.         fname[i] =  fnmex[i];
  46.         fnlen++;
  47.     }
  48.     fname[fnlen] = '\0';
  49.  
  50.     /* get file ext and len */
  51.     while (fnmex[i] && fnmex[i]!='.') {
  52.         i++;
  53.     }
  54.     if (fnmex[i] == '.')
  55.         i++;
  56.     for (felen=j=0; fnmex[j+i] && j<MAXEXT-2; j++) {
  57.         fext[j] =  fnmex[j+i];
  58.         felen++;
  59.     }
  60.     fext[felen] = '\0';
  61.  
  62.     /* Three cases:
  63.      * full filename/ext: 12345678.ABC -> 2345678A.BCX
  64.      * full file ext:     1234567.ABC  -> 1234567A.BCX
  65.      * other:             12345678.AB  -> 12345678.ABX
  66.      */
  67.     if ((fnlen == MAXFILE-1) && (felen == MAXEXT-2)) {
  68.         sprintf(fnmex,"%s%c.%s%c",fname+1,fext[0],fext+1,*bext);
  69.     } else if (felen == MAXEXT-2) {
  70.         sprintf(fnmex,"%s%c.%s%c",fname,fext[0],fext+1,*bext);
  71.     } else {
  72.         sprintf(fnmex,"%s.%s%c",fname,fext,*bext);
  73.     }
  74. }
  75.  
  76.  
  77. /* fninc : increment/add last char of/to fspec.
  78.  *         used with fappend (call fnappend once, then fninc many times
  79.  */
  80.  
  81. void
  82. fninc(fspec)
  83. char *fspec;
  84. {
  85.     char *cp;
  86.     int lastp,lastc;
  87.  
  88.     lastc = fspec[lastp = strlen(fspec)-1];
  89.     if (strchr("012345678ABCDEFGHIJKLMNOPQRSTUVWXY",lastc) != NULL) {
  90.         fspec[lastp]++;
  91.     } else if (lastc == '9') {
  92.         fspec[lastp] = 'A';
  93.     } else if (lastc == 'Z') {
  94.         for (cp=&fspec[lastp]; *cp=='Z' || *cp=='.'; cp--) {
  95.             if (*cp == 'Z') {
  96.                 *cp = '0';
  97.             }
  98.         }
  99.         if (strchr("012345678ABCDEFGHIJKLMNOPQRSTUVWXY",*cp) != NULL) {
  100.             (*cp)++;
  101.         } else if (*cp == '9') {
  102.             *cp = 'A';
  103.         } else {
  104.             if (*(cp+1) == '.') cp++;
  105.             *(cp+1) = '1';
  106.             fnappend(fspec,"0");
  107.         }
  108.     } else {
  109.         fnappend(fspec,"0");
  110.     }
  111. }
  112. #endif
  113.  
  114.  
  115. /* Rename a file, copying it if necessary. */
  116.  
  117. int
  118. move_file(from,to)
  119. char *from, *to;
  120. {
  121.     char bakname[512];
  122.     Reg1 char *s;
  123.     Reg2 int i;
  124.     Reg3 int fromfd;
  125.  
  126.     /* to stdout? */
  127.  
  128.     if (strEQ(to, "-")) {
  129. #ifdef DEBUGGING
  130.     if (debug & 4)
  131.         say2("Moving %s to stdout.\n", from);
  132. #endif
  133.     fromfd = open(from, 0);
  134.     if (fromfd < 0)
  135.         fatal2("patch: internal error, can't reopen %s\n", from);
  136.     while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
  137.         if (write(1, buf, i) == -1)
  138.         fatal1("patch: write failed\n");
  139.     Close(fromfd);
  140.     return 0;
  141.     }
  142.  
  143.     if (origprae) {
  144.             Strcpy (bakname, origprae);
  145.             Strcat(bakname, to);
  146.     } else {
  147.             Strcpy(bakname, to);
  148. #ifdef TURBOC20
  149.             fnappend(bakname, origext?origext:ORIGEXT);
  150.     }
  151.  
  152.     if (stat(to, &filestat) >= 0) {    /* output file exists */
  153.     short to_device = filestat.st_dev;
  154.     short to_mode = filestat.st_mode;
  155.     long  to_size  = filestat.st_size;
  156.     long  to_time  = filestat.st_mtime;
  157.  
  158.     /* find a backup name that is not the same file */
  159.     while (stat(bakname, &filestat) >= 0 &&
  160.         to_device == filestat.st_dev &&
  161.         to_mode == filestat.st_mode &&
  162.                 to_size == filestat.st_size &&
  163.                 to_time == filestat.st_mtime
  164.               ) {
  165.         fninc(bakname);
  166.     }
  167. #else
  168.             Strcat(bakname, origext?origext:ORIGEXT);
  169.     }
  170.     if (stat(to, &filestat) >= 0) {    /* output file exists */
  171.      dev_t to_device = filestat.st_dev;
  172.      ino_t to_inode  = filestat.st_ino;
  173.     char *simplename = bakname;
  174.     
  175.     for (s=bakname; *s; s++) {
  176.         if (*s == '/')
  177.         simplename = s+1;
  178.     }
  179.     /* find a backup name that is not the same file */
  180.     while (stat(bakname, &filestat) >= 0 &&
  181.         to_device == filestat.st_dev &&
  182.                 to_inode == filestat.st_ino
  183.               ) {
  184.         for (s=simplename; *s && !islower(*s); s++) ;
  185.         if (*s)
  186.         *s = toupper(*s);
  187.         else
  188.         Strcpy(simplename, simplename+1);
  189.     }
  190. #endif                
  191.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  192. #ifdef DEBUGGING
  193.     if (debug & 4)
  194.         say3("Moving %s to %s.\n", to, bakname);
  195. #endif
  196. #ifdef TURBOC20
  197.     copy_file(to, bakname);
  198. #else        
  199.     if (link(to, bakname) < 0) {
  200.         say3("patch: can't backup %s, output is in %s\n",
  201.         to, from);
  202.         return -1;
  203.     }
  204. #endif
  205.     while (unlink(to) >= 0) ;
  206.     }
  207. #ifdef DEBUGGING
  208.     if (debug & 4)
  209.     say3("Moving %s to %s.\n", from, to);
  210. #endif
  211. #ifdef TURBOC20
  212.     copy_file(from, to);
  213. #else
  214.     if (link(from, to) < 0) {        /* different file system? */
  215.     Reg4 int tofd;
  216.     
  217.     tofd = creat(to, 0666);
  218.     if (tofd < 0) {
  219.         say3("patch: can't create %s, output is in %s.\n",
  220.           to, from);
  221.         return -1;
  222.     }
  223.     fromfd = open(from, 0);
  224.     if (fromfd < 0)
  225.         fatal2("patch: internal error, can't reopen %s\n", from);
  226.     while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
  227.         if (write(tofd, buf, i) == -1)
  228.         fatal1("patch: write failed\n");
  229.     Close(fromfd);
  230.     Close(tofd);
  231.     }
  232. #endif
  233.     Unlink(from);
  234.     return 0;
  235. }
  236.  
  237. /* Copy a file. */
  238.  
  239. void
  240. copy_file(from,to)
  241. char *from, *to;
  242. {
  243.     Reg3 int tofd;
  244.     Reg2 int fromfd;
  245.     Reg1 int i;
  246.     
  247.     tofd = creat(to, 0666);
  248.     if (tofd < 0)
  249.     fatal2("patch: can't create %s.\n", to);
  250.     fromfd = open(from, 0);
  251.     if (fromfd < 0)
  252.     fatal2("patch: internal error, can't reopen %s\n", from);
  253.     while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
  254.     if (write(tofd, buf, i) == -1)
  255.         fatal2("patch: write (%s) failed\n", to);
  256.     Close(fromfd);
  257.     Close(tofd);
  258. }
  259.  
  260. /* Allocate a unique area for a string. */
  261.  
  262. char *
  263. savestr(s)
  264. Reg1 char *s;
  265. {
  266.     Reg3 char *rv;
  267.     Reg2 char *t;
  268.  
  269.     if (!s)
  270.     s = "Oops";
  271.     t = s;
  272.     while (*t++);
  273.     rv = malloc((MEM) (t - s));
  274.     if (rv == Nullch) {
  275.     if (using_plan_a)
  276.         out_of_mem = TRUE;
  277.     else
  278.         fatal1("patch: out of memory (savestr)\n");
  279.     }
  280.     else {
  281.     t = rv;
  282.     while (*t++ = *s++);
  283.     }
  284.     return rv;
  285. }
  286.  
  287. #if defined(lint) && defined(CANVARARG)
  288.  
  289. /*VARARGS ARGSUSED*/
  290. say(pat) char *pat; { ; }
  291. /*VARARGS ARGSUSED*/
  292. fatal(pat) char *pat; { ; }
  293. /*VARARGS ARGSUSED*/
  294. ask(pat) char *pat; { ; }
  295.  
  296. #else
  297.  
  298. /* Vanilla terminal output (buffered). */
  299.  
  300. void
  301. say(pat,arg1,arg2,arg3)
  302. char *pat;
  303. long arg1,arg2,arg3;
  304. {
  305.     fprintf(stderr, pat, arg1, arg2, arg3);
  306.     Fflush(stderr);
  307. }
  308.  
  309. /* Terminal output, pun intended. */
  310.  
  311. void                /* very void */
  312. fatal(pat,arg1,arg2,arg3)
  313. char *pat;
  314. long arg1,arg2,arg3;
  315. {
  316.     void my_exit();
  317.  
  318.     say(pat, arg1, arg2, arg3);
  319.     my_exit(1);
  320. }
  321.  
  322. /* Get a response from the user, somehow or other. */
  323.  
  324. void
  325. ask(pat,arg1,arg2,arg3)
  326. char *pat;
  327. long arg1,arg2,arg3;
  328. {
  329.     int ttyfd;
  330.     int r;
  331.     bool tty2 = isatty(2);
  332.  
  333.     Sprintf(buf, pat, arg1, arg2, arg3);
  334.     Fflush(stderr);
  335.     write(2, buf, strlen(buf));
  336.     if (tty2) {                /* might be redirected to a file */
  337.     r = read(2, buf, sizeof buf);
  338.     }
  339.     else if (isatty(1)) {        /* this may be new file output */
  340.     Fflush(stdout);
  341.     write(1, buf, strlen(buf));
  342.     r = read(1, buf, sizeof buf);
  343.     }
  344.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  345.                     /* might be deleted or unwriteable */
  346.     write(ttyfd, buf, strlen(buf));
  347.     r = read(ttyfd, buf, sizeof buf);
  348.     Close(ttyfd);
  349.     }
  350.     else if (isatty(0)) {        /* this is probably patch input */
  351.     Fflush(stdin);
  352.     write(0, buf, strlen(buf));
  353.     r = read(0, buf, sizeof buf);
  354.     }
  355.     else {                /* no terminal at all--default it */
  356.     buf[0] = '\n';
  357.     r = 1;
  358.     }
  359.     if (r <= 0)
  360.     buf[0] = 0;
  361.     else
  362.     buf[r] = '\0';
  363.     if (!tty2)
  364.     say1(buf);
  365. }
  366. #endif /* lint */
  367.  
  368. /* How to handle certain events when not in a critical region. */
  369.  
  370. void
  371. set_signals(reset)
  372. int reset;
  373. {
  374.     void my_exit();
  375. #ifndef lint
  376. #ifdef TURBOC20
  377. #ifdef VOIDSIG
  378.     static void (*intval)();
  379. #else
  380.     static int (*intval)();
  381. #endif
  382. #else
  383. #ifdef VOIDSIG
  384.     static void (*hupval)(),(*intval)();
  385. #else
  386.     static int (*hupval)(),(*intval)();
  387. #endif
  388. #endif
  389.  
  390.     if (!reset) {
  391. #ifndef TURBOC20
  392.     hupval = signal(SIGHUP, SIG_IGN);
  393.     if (hupval != SIG_IGN)
  394. #ifdef VOIDSIG
  395.         hupval = my_exit;
  396. #else
  397.         hupval = (int(*)())my_exit;
  398. #endif
  399. #endif
  400.  
  401.     intval = signal(SIGINT, SIG_IGN);
  402.     if (intval != SIG_IGN)
  403. #ifdef VOIDSIG
  404.         intval = my_exit;
  405. #else
  406.         intval = (int(*)())my_exit;
  407. #endif
  408.     }
  409. #ifndef TURBOC20
  410.     Signal(SIGHUP, hupval);
  411. #endif
  412.     Signal(SIGINT, intval);
  413. #endif
  414. }
  415.  
  416. /* How to handle certain events when in a critical region. */
  417.  
  418. void
  419. ignore_signals()
  420. {
  421. #ifndef lint
  422. #ifndef TURBOC20
  423.     Signal(SIGHUP, SIG_IGN);
  424. #endif
  425.     Signal(SIGINT, SIG_IGN);
  426. #endif
  427. }
  428.  
  429. /* Make sure we'll have the directories to create a file. */
  430.  
  431. void
  432. makedirs(filename,striplast)
  433. Reg1 char *filename;
  434. bool striplast;
  435. {
  436.     char tmpbuf[256];
  437.     Reg2 char *s = tmpbuf;
  438.     char *dirv[20];
  439.     Reg3 int i;
  440.     Reg4 int dirvp = 0;
  441.  
  442.     while (*filename) {
  443.     if (*filename == '/') {
  444.         filename++;
  445.         dirv[dirvp++] = s;
  446.         *s++ = '\0';
  447.     }
  448.     else {
  449.         *s++ = *filename++;
  450.     }
  451.     }
  452.     *s = '\0';
  453.     dirv[dirvp] = s;
  454.     if (striplast)
  455.     dirvp--;
  456.     if (dirvp < 0)
  457.     return;
  458.     strcpy(buf, "mkdir");
  459.     s = buf;
  460.     for (i=0; i<=dirvp; i++) {
  461.     while (*s) s++;
  462.     *s++ = ' ';
  463.     strcpy(s, tmpbuf);
  464.     *dirv[i] = '/';
  465.     }
  466.     system(buf);
  467. }
  468.  
  469. /* Make filenames more reasonable. */
  470.  
  471. char *
  472. fetchname(at,strip_leading,assume_exists)
  473. char *at;
  474. int strip_leading;
  475. int assume_exists;
  476. {
  477.     char *s;
  478.     char *name;
  479.     Reg1 char *t;
  480.     char tmpbuf[200];
  481.  
  482.     if (!at)
  483.     return Nullch;
  484.     s = savestr(at);
  485.     for (t=s; isspace(*t); t++) ;
  486.     name = t;
  487. #ifdef DEBUGGING
  488.     if (debug & 128)
  489.     say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
  490. #endif
  491.     if (strnEQ(name, "/dev/null", 9))    /* so files can be created by diffing */
  492.     return Nullch;            /*   against /dev/null. */
  493.     for (; *t && !isspace(*t); t++)
  494.     if (*t == '/')
  495.         if (--strip_leading >= 0)
  496.         name = t+1;
  497.     *t = '\0';
  498.     if (name != s && *s != '/') {
  499.     name[-1] = '\0';
  500.     if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
  501.         name[-1] = '/';
  502.         name=s;
  503.     }
  504.     }
  505.     name = savestr(name);
  506.     Sprintf(tmpbuf, "RCS/%s", name);
  507.     free(s);
  508.     if (stat(name, &filestat) < 0 && !assume_exists) {
  509.     Strcat(tmpbuf, RCSSUFFIX);
  510.     if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
  511.         Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
  512.         if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
  513.         free(name);
  514.         name = Nullch;
  515.         }
  516.     }
  517.     }
  518.     return name;
  519. }
  520.